#!/bin/sh

#  Copyright (C) 2014,2015,2017 Curt Brune <curt@cumulusnetworks.com>
#  Copyright (C) 2015,2016 david_yang <david_yang@accton.com>
#  Copyright (C) 2016 Pankaj Bansal <pankajbansal3073@gmail.com>
#
#  SPDX-License-Identifier:     GPL-2.0

# This file provides a GRUB menu entry for ONIE.
#
## DO NOT remove the following line:
##   ONIE_SUPPORT_BOOTCMD_FEEDING
#
# Place this file in /etc/grub.d and grub-mkconfig will use this file
# when generating a grub configuration file.
#
# There are two parts to the operation.
#
# Step 1 -- Add a chainload menu entry to the host OS GRUB
# configuration.  Everything sent to stdout will end up in the host OS
# GRUB configuration.
#
# Step 2 -- Update ONIE's GRUB configuration in the ONIE-BOOT
# partition.

# Step 1
# Depends on UEFI GRUB or Legacy BIOS GRUB

# get running machine from conf file
[ -r /etc/machine.conf ] && . /etc/machine.conf

default_chainloader="+1"
[ "${onie_firmware}" = "coreboot" ] && default_chainloader=/grub/i386-coreboot/core.elf
uefi_root=/boot/efi
onie_uefi_loader="EFI/onie/%%UEFI_BOOT_LOADER%%"
if [ -d "/sys/firmware/efi/efivars" ] && [ -r "${uefi_root}/${onie_uefi_loader}" ] ; then
    uefi_uuid=$(grub-probe --target=fs_uuid "${uefi_root}/${onie_uefi_loader}") || {
        echo "ERROR: grub-probe failed" > /dev/stderr
        echo "ERROR: failing cmd: grub-probe --target=fs_uuid ${uefi_root}/${onie_uefi_loader}" > /dev/stderr
        exit 1
    }
    cat <<EOF
# Menu entry to chainload ONIE UEFI
# Insert --unrestricted to NOT require a Secure Grub login.
menuentry ONIE {
	set root='(hd0,gpt1)'
	search --no-floppy --fs-uuid --set=root ${uefi_uuid}
	echo	'Loading ONIE ...'
	chainloader /${onie_uefi_loader}
}
EOF
else
    cat <<EOF
# Menu entry to chainload ONIE
menuentry ONIE {
	search --no-floppy --label --set=root ONIE-BOOT
	echo	'Loading ONIE ...'
	chainloader ${default_chainloader}
}
EOF
fi

# Step 2 -- Update ONIE's GRUB configuration in the ONIE-BOOT
# partition.

diag_label=$(blkid | grep -- '-DIAG"' | sed -e 's/^.*LABEL="//' -e 's/".*$//')
add_diag_bootcmd()
{
    if [ -r "$onie_root_dir/grub/diag-bootcmd.cfg" ] ; then
        cat $onie_root_dir/grub/diag-bootcmd.cfg >> $grub_cfg
        return 0
    fi

    cat <<EOF >> $grub_cfg
diag_menu="$diag_label"
EOF
    if [ -d "/sys/firmware/efi/efivars" ] && [ -f "${uefi_root}/$onie_uefi_loader" ] ; then
        # UEFI firmware
        diag_uefi_grub=$(efibootmgr -v | grep $diag_label | sed -e 's/.*)\/File(//' -e 's/)//' -e 's/\\/\//g')
        if [ -f "$uefi_root/$diag_uefi_grub" ] ; then
            cat <<EOF >> $grub_cfg
function diag_bootcmd {
  set root='(hd0,gpt1)'
  search --no-floppy --fs-uuid --set=root $uefi_uuid
  echo    "Loading $diag_label \$onie_build_platform ..."
  chainloader /$diag_uefi_grub
  boot
}
EOF
        fi
    else
        # legacy BIOS firmware
        cat <<EOF >> $grub_cfg
function diag_bootcmd {
  search --no-floppy --label --set=root $diag_label
  echo    "Loading $diag_label \$onie_build_platform ..."
  chainloader ${default_chainloader}
  boot
}
EOF
    fi
}

tmp_mnt=
onie_umount_partition()
{
    umount $tmp_mnt > /dev/null 2>&1
    rmdir $tmp_mnt || {
        echo "ERROR: Problems removing temp directory: $tmp_mnt"
        exit 1
    }
}

# Mount the ONIE partition
tmp_mnt=$(mktemp -d)
trap onie_umount_partition EXIT

mount LABEL=ONIE-BOOT $tmp_mnt || {
    echo "ERROR: Problems trying to mount ONIE-BOOT partition"
    exit 1
}

grub_root_dir="${tmp_mnt}/grub"
grub_cfg="${grub_root_dir}/grub.cfg"

onie_root_dir="${tmp_mnt}/onie"
[ -d "$onie_root_dir" ] || {
    echo "ERROR: Unable to find ONIE root directory: $onie_root_dir"
    exit 1
}

# - backward compatible with present NOS/DIAG installers
# - If NOS/DIAG installer does not export GRUB_SERIAL_COMMAND and
#   GRUB_CMDLINE_LINUX, ONIE will use the default/correct ones.
if [ -z "$GRUB_ONIE_SERIAL_COMMAND" ] ||
    [ -z "$GRUB_CMDLINE_LINUX" ] ; then
. $onie_root_dir/grub/grub-variables
fi

rm -f $grub_cfg
touch $grub_cfg

if echo -n "$GRUB_CMDLINE_LINUX" | grep -q ttyS ; then
    cat <<EOF >> $grub_cfg
# begin: serial console config

$GRUB_ONIE_SERIAL_COMMAND
terminal_input serial
terminal_output serial

# end: serial console config
EOF
fi

# Look for an ONIE compatible DIAG image and add a boot entry for it.
cat <<EOF >> $grub_cfg
# begin: diag boot command

EOF
if [ -n "$diag_label" ]  ; then
    add_diag_bootcmd
fi
cat <<EOF >> $grub_cfg

# end: diag boot command
EOF

# add the ONIE machine configuration data
cat $onie_root_dir/grub/grub-machine.cfg >> $grub_cfg

# add extra platform specific kernel command line options
cat $onie_root_dir/grub/grub-extra.cfg >> $grub_cfg

cat <<EOF >> $grub_cfg
# begin: ONIE bootargs

onie_initargs="$GRUB_CMDLINE_LINUX"
onie_initargs_default="$GRUB_CMDLINE_LINUX_DEFAULT"
onie_platformargs="$GRUB_ONIE_PLATFORM_ARGS"
onie_debugargs="$GRUB_ONIE_DEBUG_ARGS"
GRUB_ONIE_CMDLINE_LINUX="$GRUB_ONIE_CMDLINE_LINUX"

# end: ONIE bootargs
EOF

# add ONIE configuration common to all ONIE boot modes
cat $onie_root_dir/grub/grub-common.cfg >> $grub_cfg
